package com.yuven.appframework.util

import android.os.Parcelable
import com.tencent.mmkv.MMKV
import java.util.Collections

object MMKVUtil {
    /**
     * 加密MMKV的加解密密钥
     */
    val CRYPT_KEY: String = "cp2ghtfryyh6tyh2fd"

    /**
     * 加密的MMKV实例
     */
    var cryptMMKV: MMKV? = null

    /**
     * 非加密的MMKV实例
     */
    var mmkv: MMKV? = null

    init {
        mmkv = MMKV.defaultMMKV()
        cryptMMKV = MMKV.mmkvWithID("CryptMMKV", MMKV.SINGLE_PROCESS_MODE, CRYPT_KEY)
    }

    /**
     * if (value instanceof Boolean) {
    this.encodeBool(this.nativeHandle, key, (Boolean)value);
    } else if (value instanceof Integer) {
    this.encodeInt(this.nativeHandle, key, (Integer)value);
    } else if (value instanceof Long) {
    this.encodeLong(this.nativeHandle, key, (Long)value);
    } else if (value instanceof Float) {
    this.encodeFloat(this.nativeHandle, key, (Float)value);
    } else if (value instanceof Double) {
    this.encodeDouble(this.nativeHandle, key, (Double)value);
    } else if (value instanceof String) {
    this.encodeString(this.nativeHandle, key, (String)value);
    } else if (value instanceof Set) {
    this.encode(key, (Set)value);
    } else {
    simpleLog(MMKVLogLevel.LevelError, "unknown type: " + value.getClass());
    }
     */

    /**
     * 存储配置值，支持加密存储，涉及手机号码、token等用户敏感信息的存储，需要加密存储
     * @param key
     * @param value
     * @param isCrypt 是否加密存储，true-加密存储，false-非加密存储，为了兼容旧版本升级上来的数据兼容性（旧版本没有加密存储），默认为false
     */
    fun encode(key: String, value: Any?, isCrypt: Boolean = false) {
        var handlerMMKV = getHandlerMMKV(isCrypt)
        when (value) {
            is String -> handlerMMKV?.encode(key, value)
            is Int -> handlerMMKV?.encode(key, value)
            is Boolean -> handlerMMKV?.encode(key, value)
            is Float -> handlerMMKV?.encode(key, value)
            is Long -> handlerMMKV?.encode(key, value)
            is Double -> handlerMMKV?.encode(key, value)
            is ByteArray -> handlerMMKV?.encode(key, value)
            else -> return
        }
    }

    /**
     * 存储Parcelable对象，支持加密存储，涉及手机号码、token等用户敏感信息的存储，需要加密存储
     * @param key
     * @param t
     * @param isCrypt 是否加密存储，true-加密存储，false-非加密存储，为了兼容旧版本升级上来的数据兼容性（旧版本没有加密存储），默认为false
     */
    fun <T : Parcelable> encode(key: String, t: T?, isCrypt: Boolean = false) {
        var handlerMMKV = getHandlerMMKV(isCrypt)
        handlerMMKV?.encode(key, t)
    }

    /**
     * 存储Set列表，支持加密存储，涉及手机号码、token等用户敏感信息的存储，需要加密存储
     * @param key
     * @param sets
     * @param isCrypt 是否加密存储，true-加密存储，false-非加密存储，为了兼容旧版本升级上来的数据兼容性（旧版本没有加密存储），默认为false
     */
    fun encode(key: String, sets: Set<String>?, isCrypt: Boolean = false) {
        var handlerMMKV = getHandlerMMKV(isCrypt)
        handlerMMKV?.encode(key, sets)
    }

    /**
     * 获取int值
     * @param key
     * @param isCrypt 是否加密存储，true-加密存储，false-非加密存储，为了兼容旧版本升级上来的数据兼容性（旧版本没有加密存储），默认为false
     */
    fun decodeInt(key: String, isCrypt: Boolean = false): Int? {
        var handlerMMKV = getHandlerMMKV(isCrypt)
        return handlerMMKV?.decodeInt(key, 0)
    }

    fun decodeInt2(key: String, isCrypt: Boolean = false): Int? {
        var handlerMMKV = getHandlerMMKV(isCrypt)
        return handlerMMKV?.decodeInt(key, -1)
    }

    /**
     * 获取Double值
     * @param key
     * @param isCrypt 是否加密存储，true-加密存储，false-非加密存储，为了兼容旧版本升级上来的数据兼容性（旧版本没有加密存储），默认为false
     */
    fun decodeDouble(key: String, isCrypt: Boolean = false): Double? {
        var handlerMMKV = getHandlerMMKV(isCrypt)
        return handlerMMKV?.decodeDouble(key, 0.00)
    }

    /**
     * 获取Long值
     * @param key
     * @param isCrypt 是否加密存储，true-加密存储，false-非加密存储，为了兼容旧版本升级上来的数据兼容性（旧版本没有加密存储），默认为false
     */
    fun decodeLong(key: String, isCrypt: Boolean = false): Long? {
        var handlerMMKV = getHandlerMMKV(isCrypt)
        return handlerMMKV?.decodeLong(key, 0L)
    }

    fun decodeBoolean(key: String, defValue: Boolean? = false, isCrypt: Boolean = false): Boolean? {
        var handlerMMKV = getHandlerMMKV(isCrypt)
        return handlerMMKV?.decodeBool(key, defValue ?: false)
    }

    /**
     * 获取Float值
     * @param key
     * @param isCrypt 是否加密存储，true-加密存储，false-非加密存储，为了兼容旧版本升级上来的数据兼容性（旧版本没有加密存储），默认为false
     */
    fun decodeFloat(key: String, isCrypt: Boolean = false): Float? {
        var handlerMMKV = getHandlerMMKV(isCrypt)
        return handlerMMKV?.decodeFloat(key, 0F)
    }

    /**
     * 获取ByteArray值
     * @param key
     * @param isCrypt 是否加密存储，true-加密存储，false-非加密存储，为了兼容旧版本升级上来的数据兼容性（旧版本没有加密存储），默认为false
     */
    fun decodeByteArray(key: String, isCrypt: Boolean = false): ByteArray? {
        var handlerMMKV = getHandlerMMKV(isCrypt)
        return handlerMMKV?.decodeBytes(key)
    }

    /**
     * 获取String值
     * @param key
     * @param isCrypt 是否加密存储，true-加密存储，false-非加密存储，为了兼容旧版本升级上来的数据兼容性（旧版本没有加密存储），默认为false
     */
    fun decodeString(key: String, isCrypt: Boolean = false): String? {
        var handlerMMKV = getHandlerMMKV(isCrypt)
        return handlerMMKV?.decodeString(key, null)
    }

    /**
     * 获取Parcelable对象值
     * @param key
     * @param isCrypt 是否加密存储，true-加密存储，false-非加密存储，为了兼容旧版本升级上来的数据兼容性（旧版本没有加密存储），默认为false
     */
    fun <T : Parcelable> decodeParcelable(
        key: String,
        tClass: Class<T>,
        isCrypt: Boolean = false
    ): T? {
        var handlerMMKV = getHandlerMMKV(isCrypt)
        return handlerMMKV?.decodeParcelable(key, tClass)
    }

    /**
     * 获取Set列表值
     * @param key
     * @param isCrypt 是否加密存储，true-加密存储，false-非加密存储，为了兼容旧版本升级上来的数据兼容性（旧版本没有加密存储），默认为false
     */
    fun decodeStringSet(key: String, isCrypt: Boolean = false): Set<String>? {
        var handlerMMKV = getHandlerMMKV(isCrypt)
        return handlerMMKV?.decodeStringSet(key, Collections.emptySet())
    }

    fun removeKey(key: String) {
        mmkv?.removeValueForKey(key)
        cryptMMKV?.removeValueForKey(key)
    }

    fun clearAll() {
        mmkv?.clearAll()
        cryptMMKV?.clearAll()
    }

    /**
     * 根据是否需要加密获取对应的MMKV操作实例
     */
    private fun getHandlerMMKV(isCrypt: Boolean = false): MMKV? {
        return if (isCrypt) cryptMMKV else mmkv
    }

}